package models

import (
	"errors"
	"reflect"
	"strings"

	"github.com/beego/beego/v2/client/orm"
)

type Video_call_price struct {
	AnchorId  int64 `orm:"column(anchor_id);pk"`
	PriceType int   `orm:"column(price_type)"`
	Price     int   `orm:"column(price)"`
}

func init() {
	orm.RegisterModel(new(Video_call_price))
}

// AddVideo_call_price insert a new Video_call_price into database and returns
// last inserted AnchorId on success.
func AddVideo_call_price(m *Video_call_price) (anchorId int64, err error) {
	o := orm.NewOrm()
	anchorId, err = o.Insert(m)
	return
}

// GetVideo_call_priceById retrieves Video_call_price by Id. Returns error if
// Id doesn't exist
func GetVideo_call_priceByAnchorId(anchorId int64, priceType int) (v *Video_call_price, err error) {
	o := orm.NewOrm()
	v = &Video_call_price{}
	if err = o.QueryTable(new(Video_call_price)).Filter("anchor_id", anchorId).Filter("price_type", priceType).RelatedSel().One(v); err == nil {
		return v, nil
	}
	return nil, err
}

func GetVideo_call_pricesByAnchorId(anchorId int64) ([]Video_call_price, error) {
	result := []Video_call_price{}
	fields := []string{"price_type", "price"}
	//order := []string{"price_type"}

	_, err := orm.NewOrm().QueryTable(new(Video_call_price)).Filter("anchor_id", anchorId).All(&result, fields...)

	if err != nil {
		return nil, err
	}
	return result, nil
}

func GetVideo_call_pricesByAnchorAndType(anchorId int64, priceType int) ([]Video_call_price, error) {
	result := []Video_call_price{}
	fields := []string{"price_type", "price"}
	//order := []string{"price_type"}

	_, err := orm.NewOrm().QueryTable(new(Video_call_price)).Filter("anchor_id", anchorId).Filter("price_type", priceType).All(&result, fields...)

	if err != nil {
		return nil, err
	}
	return result, nil
}

// GetAllVideo_call_price retrieves all Video_call_price matches certain condition. Returns empty list if
// no records exist
func GetAllVideo_call_price(query map[string]string, fields []string, sortby []string, order []string,
	offset int64, limit int64) (ml []interface{}, err error) {
	o := orm.NewOrm()
	qs := o.QueryTable(new(Video_call_price))
	// query k=v
	for k, v := range query {
		// rewrite dot-notation to Object__Attribute
		k = strings.Replace(k, ".", "__", -1)
		qs = qs.Filter(k, v)
	}
	// order by:
	var sortFields []string
	if len(sortby) != 0 {
		if len(sortby) == len(order) {
			// 1) for each sort field, there is an associated order
			for i, v := range sortby {
				orderby := ""
				if order[i] == "desc" {
					orderby = "-" + v
				} else if order[i] == "asc" {
					orderby = v
				} else {
					return nil, errors.New("Error: Invalid order. Must be either [asc|desc]")
				}
				sortFields = append(sortFields, orderby)
			}
			qs = qs.OrderBy(sortFields...)
		} else if len(sortby) != len(order) && len(order) == 1 {
			// 2) there is exactly one order, all the sorted fields will be sorted by this order
			for _, v := range sortby {
				orderby := ""
				if order[0] == "desc" {
					orderby = "-" + v
				} else if order[0] == "asc" {
					orderby = v
				} else {
					return nil, errors.New("Error: Invalid order. Must be either [asc|desc]")
				}
				sortFields = append(sortFields, orderby)
			}
		} else if len(sortby) != len(order) && len(order) != 1 {
			return nil, errors.New("Error: 'sortby', 'order' sizes mismatch or 'order' size is not 1")
		}
	} else {
		if len(order) != 0 {
			return nil, errors.New("Error: unused 'order' fields")
		}
	}

	var l []Video_call_price
	qs = qs.OrderBy(sortFields...).RelatedSel()
	if _, err = qs.Limit(limit, offset).All(&l, fields...); err == nil {
		if len(fields) == 0 {
			for _, v := range l {
				ml = append(ml, v)
			}
		} else {
			// trim unused fields
			for _, v := range l {
				m := make(map[string]interface{})
				val := reflect.ValueOf(v)
				typ := val.Type()
				for _, fname := range fields {
					//m[fname] = val.FieldByName(fname).Interface()
					field, ok := typ.FieldByName(fname)
					if ok && field.IsExported() {
						value := val.Field(field.Index[0])
						m[fname] = value.Interface()
					}
				}

				ml = append(ml, m)
			}
		}
		return ml, nil
	}
	return nil, err
}

// UpdateVideo_call_price updates Video_call_price by Id and returns error if
// the record to be updated doesn't exist
func UpdateVideo_call_priceById(m *Video_call_price) (err error) {
	o := orm.NewOrm()
	v := Video_call_price{AnchorId: m.AnchorId}
	// ascertain anchor_id exists in the database
	if err = o.Read(&v); err == nil {
		//var num int64
		if _, err = o.Update(m); err != nil {
			return
		}
	}
	return
}

// UpdateVideo_call_price updates Video_call_price by Id and returns error if
// the record to be updated doesn't exist
func UpdateVideo_call_priceByIdAndType(m *Video_call_price) error {

	updateData := map[string]interface{}{"price": m.Price}
	num, err := orm.NewOrm().QueryTable(new(Video_call_price)).Filter("anchor_id", m.AnchorId).Filter("price_type", m.PriceType).Update(updateData)

	if err == nil {
		return err
	}

	if num == 0 {
		return errors.New("更新失败")
	}

	return nil
}

// DeleteVideo_call_price deletes Video_call_price by Id and returns error if
// the record to be deleted doesn't exist
func DeleteVideo_call_price(anchorId int64) (err error) {
	o := orm.NewOrm()
	v := Video_call_price{AnchorId: anchorId}
	// ascertain anchorId exists in the database
	if err = o.Read(&v); err == nil {
		//var num int64
		if _, err = o.Delete(&Video_call_price{AnchorId: anchorId}); err != nil {
			return
		}
	}
	return
}
